package vip.bblog.elasticsearch.config;

import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;

import javax.servlet.http.HttpServletResponse;

/**
 * @author <a href="1396513066@qq.com">Yu Yong</a>
 * @version 1.0
 * @date 2019年03月24日 13:51
 * @desc ResourceServer 资源服务配置
 * @url <a href="https://projects.spring.io/spring-security-oauth/docs/oauth2.html#resource-server-configuration"></a>
 * 该@EnableResourceServer注释添加类型的过滤器OAuth2AuthenticationProcessingFilter自动Spring Security的过滤器链，解析access_token
 * @see org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationProcessingFilter
 * 解析后通过DefaultTokenServices，根据access_token和认证服务器配置里的TokenStore(token存储方式)从redis或jwt中解析出用户信息
 * @see org.springframework.security.oauth2.provider.token.DefaultTokenServices
 * 认证中心的@EnableResourceServer和别的微服务里的@EnableResourceServer不同，别的微服务是通过UserInfoTokenServices来获取用户信息的<br>
 * @see org.springframework.boot.autoconfigure.security.oauth2.resource.UserInfoTokenServices
 * @see org.springframework.boot.autoconfigure.security.oauth2.OAuth2AutoConfiguration 入口，一直点到ResourceServerTokenServicesConfiguration
 * 这里面 UserInfoTokenServicesConfiguration 如果不是token认证服务器
 * 它就会注入UserInfoTokenServices到容器，然后 ResourceServerConfiguration 就会把UserInfoTokenServices设置到OAuth2AuthenticationManager中
 * @see ResourceServerSecurityConfigurer 的tokenServices(HttpSecurity http)相关的就可以看到原理了，如果没有ResourceServerTokenServices，它就会
 * 生成DefaultTokenServices
 */
@EnableResourceServer
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class ResourceServer extends ResourceServerConfigurerAdapter {

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.csrf().disable().exceptionHandling()
                .authenticationEntryPoint(
                        (request, response, authException) -> response.sendError(HttpServletResponse.SC_UNAUTHORIZED))
                .and().authorizeRequests().antMatchers("/article/**").permitAll().anyRequest()
                .authenticated();
    }

    @Bean
    BCryptPasswordEncoder bCryptPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }

}
